import 'dart:async';
import 'package:geolocator/geolocator.dart';
import 'package:latlong2/latlong.dart';
import 'package:spring_fairy/model/config.dart';
import 'package:spring_fairy/model/mood_track_point.dart';
import 'package:spring_fairy/model/point_record.dart';
import 'package:spring_fairy/model/store.dart';
import 'package:spring_fairy/util/get_current_position.dart';
import 'model/locus.dart';

///记录运动轨迹
///每一天只会生成一条轨迹?
class FootPrints {
  late Locus? _locus;

  //记录移动轨迹是否发生改变
  StreamController<void>? _streamController;

  StreamController<MoodTrackPoint>? _markingPointController;

  Position? _lastPosition;

  bool _hasTracking = false;

  int? moodTypeId;

  //记录标记点定时器
  Timer? _timer;

  bool get hasTracking => _hasTracking;

  //上一个标记点的坐标
  Position? _lastPointPosition;

  ///获取运动轨迹
  Locus getLocus() {
      if(_locus == null) {
        throw Exception("please start tracking");
      }
      return _locus!;
  }

  ///监听轨迹变化
  Stream<void> stream() {
    if(_streamController == null) {
      throw Exception("please start tracking");
    }
    return _streamController!.stream;
  }

  Stream<MoodTrackPoint> markingPointStream() {
    if(!_hasTracking) {
      throw Exception("please start tracking");
    }
    return _markingPointController!.stream;
  }

  ///开始记录轨迹
  void startTracking() {
    if(_hasTracking) {
      return ;
    }

    _hasTracking = true;
    _streamController = StreamController();
    _markingPointController = StreamController();
    _locus = Locus();
    getCurrentPosition().then((position) {
      _lastPosition = position;
    });

    _timer = Timer.periodic(AppConfig.RECORDING_INTERVAL, (timer) async {
      Position currentPosition = await getCurrentPosition();
      //在某个地点间隔n分钟停留则标记该地点，如果一直停留在该附近，则只记录一次
      if(_hasStay(currentPosition, _lastPosition!)) {
        //查询缓存中是否有该地点？
        var points = Store.getPoints();
        for(var point in points) {
          double distance = Geolocator.distanceBetween(point.latitude!, point.longitude!, currentPosition.latitude, currentPosition.longitude);
          if(distance <= AppConfig.MOVEMENT_DISTANCE) {
            _markingPointController?.add(point);
            _lastPointPosition = currentPosition;
            return ;
          }
        }

        PointRecord record = await PointRecord.searchAddress(LatLng(currentPosition.latitude, currentPosition.longitude));

        MoodTrackPoint point = MoodTrackPoint(
          latitude: currentPosition.latitude,
          longitude: currentPosition.longitude,
          moodTime: DateTime.now(),
          weather: record.weather,
          temperature: record.temperature,
          createdAt: DateTime.now(),
          locationName: record.address,
          moodLevel: 1,
          moodTypeId: moodTypeId ?? Store.moodTypes().firstWhere((e) => e.name == 'location').id
        );
        _markingPointController?.add(point);
        _lastPointPosition = currentPosition;
      }
      _lastPosition = currentPosition;
    });
  }

  ///停止记录轨迹
  void stopTracking() {
    if(!_hasTracking) {
      return ;
    }

    _hasTracking = false;
    _streamController?.close();
    _streamController = null;
    _timer?.cancel();
    _markingPointController?.close();
  }


  //在有个地点停留超过固定时间记录该标记点
  bool _hasStay(Position currentPosition,Position lastPosition) {
    double distance = Geolocator.distanceBetween(
      currentPosition.latitude,
      currentPosition.longitude,
      lastPosition.latitude,
      lastPosition.longitude,
    );

    //与上一个坐标物理距离小于DISTANCE,并且和上一个标记点不是同一个地方
    bool isSamePlace = distance <= AppConfig.MOVEMENT_DISTANCE;


    return isSamePlace;
  }

}